/*!
 * \file t3_analysis.c
 *
 * \brief t3数据包解析
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 *
 * \version 2.0
 * \author wuwk
 * \date 2015/11/20
 *
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#undef _GNU_SOURCE

#if defined(FRLINUX4) || defined(FRLINUX5)
    #include "endian_dbg.h"
#else
    #include <endian.h>
#endif

#include "frcomm.h"
#include "t3_core.h"
#include "t3_ejb.h"
#include "t3_analysis.h"
#include "wls_parse_message.h"


/*!
 * 取得responseId
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __t3_get_responseid(L7session_t3_private *p_st_private
                                , Frbyte_Packet *p_st_data)
{
    uint32_t u32_id = 0;

    if (p_st_private == NULL || p_st_data == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 4)
        return APM_L7_ANALYZE_TODO;

    if (bytebuff_get_int(p_st_data, 4, &u32_id, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    p_st_private->ui_responseid = u32_id;

    return FR_SUCC;
}

/*!
 * 取得methodId
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __t3_get_methodid(L7session_t3_private *p_st_private
                              , Frbyte_Packet *p_st_data)
{
    uint32_t u32_id = 0;

    if (p_st_private == NULL || p_st_data == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 26)
        return APM_L7_ANALYZE_TODO;

    bytebuff_skip(p_st_data, 22);

    if (bytebuff_get_int(p_st_data, 4, &u32_id, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    p_st_private->i_methodid = u32_id;

    return FR_SUCC;
}

/*!
 * 服务器信息解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __t3_destination_analysis(L7session_t3_private *p_st_private
                                      , Frbyte_Packet *p_st_data)
{
    L7Session_t3 *p_st_session = NULL;
    uint16_t u16_flag = 0;
    uint16_t u16_persistentstore = 0;
    uint16_t u16_persistentstore_len = 0;
    uint16_t u16_len = 0;
    char *p_module_name = NULL;
    char *p_webl_server = NULL;
    int i_type = 0;
    int i_flag = 0;

    if (p_st_private == NULL || p_st_private->p_st_session == NULL
        || p_st_data == NULL)
        return FR_FAIL;

    p_st_session = p_st_private->p_st_session;

//    bytebuff_skip(p_st_data, 12);
    if (bytebuff_get_short(p_st_data, 2, &u16_flag, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    i_type = (u16_flag & 0xF) >> 0 & 0xFF;
    // topic
    if (i_type == 2)
        p_st_private->is_topic = 1;

    i_flag = (u16_flag & 0xF00) >> 8 & 0xFF;

    bytebuff_skip(p_st_data, 2);
    // JMS模块名长度
    if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    p_module_name = (char *)frmalloc(u16_len + 1);
    if (p_module_name == NULL)
        return FR_FAIL;
    memset(p_module_name, 0x00, u16_len + 1);

    // JMS模块名
    if (bytebuff_get_bytes(p_st_data, p_module_name, u16_len) == FR_FAIL)
        goto err;

    // 添加到session
    if (p_st_session->p_jms_module == NULL)
    {
        p_st_session->p_jms_module = frstrdup(p_module_name);
        if (p_st_session->p_jms_module == NULL)
            goto err;
    }

    frfree(p_module_name);
    p_module_name = NULL;
    bytebuff_skip(p_st_data, 1);
    // 长度
    if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        goto err;
    bytebuff_skip(p_st_data, u16_len);

    bytebuff_skip(p_st_data, 15);
    // weblogic_server长度
    if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        goto err;

    p_webl_server = (char *)frmalloc(u16_len + 1);
    if (p_webl_server == NULL)
        goto err;
    memset(p_webl_server, 0x00, u16_len + 1);

    // weblogic_server名
    if (bytebuff_get_bytes(p_st_data, p_webl_server, u16_len) == FR_FAIL)
        goto err;

    // 添加到session
    if (p_st_session->p_weblogic_server == NULL)
    {
        p_st_session->p_weblogic_server = frstrdup(p_webl_server);
        if (p_st_session->p_weblogic_server == NULL)
            goto err;
    }

    frfree(p_webl_server);
    p_webl_server = NULL;

    bytebuff_skip(p_st_data, 17);
//    if ((u16_flag & 0x2000) != 0)
//    {
//        // skip backendId and destinationId
//        if (wls_backend_destination_id(p_st_data, 0, 0) == FR_FAIL)
//            return FR_FAIL;
//    }

    // multicastAddress,port
    if ((u16_flag & 0x4000) != 0)
    {
        // multicastAddress
        if (bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN) == FR_FAIL)
            goto err;
        if (u16_len != 0)
            bytebuff_skip(p_st_data, u16_len);

        // port
        bytebuff_skip(p_st_data, 4);
    }

    if ((u16_flag & 0x8000) != 0)
    {
        if (wls_skip_dispatcher_id(p_st_data, 0) == FR_FAIL)
            return FR_FAIL;
    }

    if (i_flag >= 5)
    {
        if (bytebuff_get_short(p_st_data, 2, &u16_persistentstore, BYTE_BIG_ENDIAN) == FR_FAIL)
            goto err;

        if (u16_persistentstore & 0x1)
        {
            // 持久性存储
            if (bytebuff_get_short(p_st_data, 2, &u16_persistentstore_len, BYTE_BIG_ENDIAN) == FR_FAIL)
                goto err;
            bytebuff_skip(p_st_data, u16_persistentstore_len);
        }
    }

    return FR_SUCC;

err:
    if (p_module_name)
        frfree(p_module_name);
    if (p_webl_server)
        frfree(p_webl_server);

    return FR_FAIL;
}

/*!
 * t3 producer解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __t3_producer_create(L7session_t3_private *p_st_private
                                   , Frbyte_Packet *p_st_data)
{
    L7Session_t3 *p_st_session = NULL;
    char *p_jms_server = NULL;
    char *p_module_queue = NULL;
    char *p_queue = NULL;
    uint8_t u8_len = 0;
    uint32_t u32_flag = 0;
    int j = 0;

    if (p_st_private == NULL || p_st_private->p_st_session == NULL || p_st_data == NULL)
        return FR_FAIL;

    p_st_session = p_st_private->p_st_session;

    if (bytebuff_get_int(p_st_data, 4, &u32_flag, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    j = u32_flag & 0xFF;
    if (j != 1)
        return FR_FAIL;

    // read Request
    if (wls_request_read(p_st_data, 0) == FR_FAIL)
        return FR_FAIL;

    if (u32_flag & 0x700)
    {
        if (__t3_destination_analysis(p_st_private, p_st_data) == FR_FAIL)
            return FR_FAIL;
    }

    bytebuff_skip(p_st_data, 5);
    // JMS server长度
    if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
        goto err;

    p_jms_server = (char *)frmalloc(u8_len + 1);
    if (p_jms_server == NULL)
        goto err;
    memset(p_jms_server, 0x00, u8_len + 1);

    // JMS server名
    if (bytebuff_get_bytes(p_st_data, p_jms_server, u8_len) == FR_FAIL)
        goto err;

    // 添加到session
    if (p_st_session->p_jms_server == NULL)
    {
        p_st_session->p_jms_server = frstrdup(p_jms_server);
        if (p_st_session->p_jms_server == NULL)
            goto err;
    }

    frfree(p_jms_server);
    p_jms_server = NULL;

    bytebuff_skip(p_st_data, 4);
    // 模块+队列名长度
    if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
        goto err;

    p_module_queue = (char *)frmalloc(u8_len + 1);
    if (p_module_queue == NULL)
        goto err;
    memset(p_module_queue, 0x00, u8_len + 1);

    // 模块+队列名
    if (bytebuff_get_bytes(p_st_data, p_module_queue, u8_len) == FR_FAIL)
        goto err;

    // 模块名和队列名分隔符
    p_queue = strchr(p_module_queue, '!');
    if (p_queue == NULL)
        goto err;

    p_queue++;
    // 添加到session
    if (p_st_session->p_queue != NULL)
        frfree(p_st_session->p_queue);

    p_st_session->p_queue = frstrdup(p_queue);
    if (p_st_session->p_queue == NULL)
        goto err;

    frfree(p_module_queue);

    return FR_SUCC;

err:
    if (p_jms_server)
        frfree(p_jms_server);
    if (p_module_queue)
        frfree(p_module_queue);

    return FR_FAIL;
}

/*!
 * t3 browser解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __t3_browser_create(L7session_t3_private *p_st_private
                                   , Frbyte_Packet *p_st_data)
{
    L7Session_t3 *p_st_session = NULL;
    char *p_jms_server = NULL;
    char *p_module_queue = NULL;
    char *p_queue = NULL;
    uint8_t u8_len = 0;
    uint32_t u32_flag = 0;
    int j = 0;

    if (p_st_private == NULL || p_st_private->p_st_session == NULL || p_st_data == NULL)
        return FR_FAIL;

    p_st_session = p_st_private->p_st_session;

    if (bytebuff_get_int(p_st_data, 4, &u32_flag, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    j = u32_flag & 0xFF;
    if (j != 1)
        return FR_FAIL;

    // read Request
    if (wls_request_read(p_st_data, 0) == FR_FAIL)
        return FR_FAIL;

    if ((u32_flag & 0x2000) == 0)
    {
        if (__t3_destination_analysis(p_st_private, p_st_data) == FR_FAIL)
            return FR_FAIL;
    }

    // messageSelector
    if (u32_flag & 0x100)
    {
        if (wls_skip_utf(p_st_data) == FR_FAIL)
            return FR_FAIL;
    }

    bytebuff_skip(p_st_data, 5);
    // JMS server长度
    if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
        goto err;

    p_jms_server = (char *)frmalloc(u8_len + 1);
    if (p_jms_server == NULL)
        goto err;
    memset(p_jms_server, 0x00, u8_len + 1);

    // JMS server名
    if (bytebuff_get_bytes(p_st_data, p_jms_server, u8_len) == FR_FAIL)
        goto err;

    // 添加到session
    if (p_st_session->p_jms_server == NULL)
    {
        p_st_session->p_jms_server = frstrdup(p_jms_server);
        if (p_st_session->p_jms_server == NULL)
            goto err;
    }

    frfree(p_jms_server);
    p_jms_server = NULL;

    bytebuff_skip(p_st_data, 4);
    // 模块+队列名长度
    if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
        goto err;

    p_module_queue = (char *)frmalloc(u8_len + 1);
    if (p_module_queue == NULL)
        goto err;
    memset(p_module_queue, 0x00, u8_len + 1);

    // 模块+队列名
    if (bytebuff_get_bytes(p_st_data, p_module_queue, u8_len) == FR_FAIL)
        goto err;

    // 模块名和队列名分隔符
    p_queue = strchr(p_module_queue, '!');
    if (p_queue == NULL)
        goto err;

    p_queue++;
    // 添加到session
    if (p_st_session->p_queue != NULL)
        frfree(p_st_session->p_queue);

    p_st_session->p_queue = frstrdup(p_queue);
    if (p_st_session->p_queue == NULL)
        goto err;

    frfree(p_module_queue);

    return FR_SUCC;

err:
    if (p_jms_server)
        frfree(p_jms_server);
    if (p_module_queue)
        frfree(p_module_queue);

    return FR_FAIL;
}

/*!
 * t3 发送消息解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 * \param *p_st_body_data   (Frreport_body_data 上报链表)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __t3_sendmsg_analysis(L7session_t3_private *p_st_private
                                  , Frbyte_Packet *p_st_data
                                  , Frreport_body_data *p_st_body_data)
{
    L7Session_t3 *p_st_session = NULL;
    char arr_title[64];
    char arr_key[64];
    int i_ret = 0;

    if (p_st_private == NULL || p_st_private->p_st_session == NULL
        || p_st_data == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    p_st_session = p_st_private->p_st_session;

    // method上报
    i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_METHOD_REQ, "PUT");
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (p_st_session->p_title)
        frfree(p_st_session->p_title);

    if (p_st_session->p_queue != NULL)
    {
        // title
        snprintf(arr_title, sizeof(arr_title), "PUT %s", p_st_session->p_queue);
        p_st_session->p_title = frstrdup(arr_title);
        if (p_st_session->p_title == NULL)
            return FR_FAIL;

        // queue/topic
        if (p_st_private->is_topic == 1)
            i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_REQ_TOPIC, p_st_session->p_queue);
        else
            i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_REQ_QUE, p_st_session->p_queue);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }
    else
    {
        // title
        snprintf(arr_title, sizeof(arr_title), "PUT");
        p_st_session->p_title = frstrdup(arr_title);
        if (p_st_session->p_title == NULL)
            return FR_FAIL;
    }
    memset(arr_key, 0x00, sizeof(arr_key));
    strcpy(arr_key, APM_REPORT_KEY_REQ);

    i_ret = wls_message_analysis(p_st_data, p_st_body_data, arr_key, 0, 0);

    return i_ret;
}

/*!
 * t3 consumer解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 * \param *p_st_body_data   (Frreport_body_data 上报链表)
 * \param *i_need_report     (int 是否需要上报)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __t3_consumer_create(L7session_t3_private *p_st_private
                                   , Frbyte_Packet *p_st_data
                                   , Frreport_body_data *p_st_body_data
                                   , int *i_need_report)
{
    L7Session_t3 *p_st_session = NULL;
    char *p_jms_server = NULL;
    char *p_module_queue = NULL;
    char *p_queue = NULL;
    char arr_title[64];
    uint8_t u8_len = 0;
    uint32_t u32_flag = 0;
    int j = 0;
    int i_ret = 0;

    if (p_st_private == NULL || p_st_private->p_st_session == NULL
        || p_st_private->p_st_fragment == NULL || p_st_data == NULL)
        return FR_FAIL;

    p_st_session = p_st_private->p_st_session;

    if (bytebuff_get_int(p_st_data, 4, &u32_flag, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    j = u32_flag & 0xFF;
    if (j < 1 || j > 14)
        return FR_FAIL;

    // read Request
    if (wls_request_read(p_st_data, 0) == FR_FAIL)
        return FR_FAIL;

    // clientId
    if (u32_flag & 0x100)
    {
        if (wls_skip_utf(p_st_data) == FR_FAIL)
            return FR_FAIL;
    }

    // name
    if (u32_flag & 0x200)
    {
        if (wls_skip_utf(p_st_data) == FR_FAIL)
            return FR_FAIL;
    }

    // selector
    if (u32_flag & 0x400)
    {
        if (wls_skip_utf(p_st_data) == FR_FAIL)
            return FR_FAIL;
    }

    if (__t3_destination_analysis(p_st_private, p_st_data) == FR_FAIL)
        return FR_FAIL;

    // messagesMaximum
    if (bytebuff_skip(p_st_data, 4) == FR_FAIL)
        return FR_FAIL;

    // redeliveryDelay
    if (u32_flag & 0x1000)
    {
        if (bytebuff_skip(p_st_data, 8) == FR_FAIL)
            return FR_FAIL;
    }

    // consumerReconnectInfo
    if (u32_flag & 0x4000)
    {
        if (wls_read_consumer_reconnectinfo(p_st_data) == FR_FAIL)
            return FR_FAIL;
    }

    // subscriptionSharingPolicy
    if (j == 14)
    {
        if (bytebuff_skip(p_st_data, 4) == FR_FAIL)
            return FR_FAIL;
    }

    bytebuff_skip(p_st_data, 5);
    // JMS server长度
    if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
        goto err;

    p_jms_server = (char *)frmalloc(u8_len + 1);
    if (p_jms_server == NULL)
        goto err;
    memset(p_jms_server, 0x00, u8_len + 1);

    // JMS server名
    if (bytebuff_get_bytes(p_st_data, p_jms_server, u8_len) == FR_FAIL)
        goto err;

    // 添加到session
    if (p_st_session->p_jms_server == NULL)
    {
        p_st_session->p_jms_server = frstrdup(p_jms_server);
        if (p_st_session->p_jms_server == NULL)
            goto err;
    }

    frfree(p_jms_server);
    p_jms_server = NULL;

    bytebuff_skip(p_st_data, 4);
    // 模块+队列名长度
    if (bytebuff_get_char(p_st_data, &u8_len) == FR_FAIL)
        goto err;

    p_module_queue = (char *)frmalloc(u8_len + 1);
    if (p_module_queue == NULL)
        goto err;
    memset(p_module_queue, 0x00, u8_len + 1);

    // 模块+队列名
    if (bytebuff_get_bytes(p_st_data, p_module_queue, u8_len) == FR_FAIL)
        goto err;

    // 模块名和队列名分隔符
    p_queue = strchr(p_module_queue, '!');
    if (p_queue == NULL)
        goto err;

    p_queue++;
    // 添加到session
    if (p_st_session->p_queue == NULL)
    {
        p_st_session->p_queue = frstrdup(p_queue);
        if (p_st_session->p_queue == NULL)
            goto err;
    }

    frfree(p_module_queue);

    if (p_st_private->is_topic == 1)
    {
        i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_SUB_QUE, p_st_session->p_queue);
        if (i_ret == FR_FAIL)
            return FR_FAIL;

        snprintf(arr_title, sizeof(arr_title), "SUB %s", p_st_session->p_queue);
        // title
        if (p_st_session->p_title == NULL)
        {
            p_st_session->p_title = frstrdup(arr_title);
            if (p_st_session->p_title == NULL)
                goto err;
        }

        p_st_private->i_type = T3_SUB;
        *i_need_report = T3_YES;
    }

    return FR_SUCC;

err:
    if (p_jms_server)
        frfree(p_jms_server);
    if (p_module_queue)
        frfree(p_module_queue);

    return FR_FAIL;
}

/*!
 * t3 接收消息解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 * \param *p_st_body_data   (Frreport_body_data 上报链表)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __t3_pushmsg_analysis(L7session_t3_private *p_st_private
                                  , Frbyte_Packet *p_st_data
                                  , Frreport_body_data *p_st_body_data)
{
    L7Session_t3 *p_st_session = NULL;
    char arr_title[64];
    char arr_key[64];
    int i_ret = 0;

    if (p_st_private == NULL || p_st_private->p_st_session == NULL
        || p_st_data == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    p_st_session = p_st_private->p_st_session;

    memset(arr_key, 0x00, sizeof(arr_key));
    // method上报
//    i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_METHOD_RESP, "GET");
//    if (i_ret == FR_FAIL)
//        return FR_FAIL;

    // title
    if (p_st_session->p_queue != NULL)
    {
        snprintf(arr_title, sizeof(arr_title), "NOTIFY %s", p_st_session->p_queue);

        // queue/topic
        if (p_st_private->is_topic == 1)
            i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_NOTIFY_TOPIC, p_st_session->p_queue);
        else
            i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_NOTIFY_QUE, p_st_session->p_queue);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
    }
    else
    {
        snprintf(arr_title, sizeof(arr_title), "NOTIFY");
    }

    if (p_st_session->p_title)
        frfree(p_st_session->p_title);
    p_st_session->p_title = frstrdup(arr_title);
    if (p_st_session->p_title == NULL)
        return FR_FAIL;

    p_st_private->i_type = T3_NOTIFY;
    strcpy(arr_key, APM_REPORT_KEY_NOTIFY);

//    if (p_st_private->is_topic == 1)
//    {
//        // method上报
//        i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_METHOD_RESP, "GET");
//        if (i_ret == FR_FAIL)
//            return FR_FAIL;
//
//        // title
//        if (p_st_session->p_queue != NULL)
//        {
//            snprintf(arr_title, sizeof(arr_title), "NOTIFY %s", p_st_session->p_queue);
//
//            // queue
//            i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_NOTIFY_TOPIC, p_st_session->p_queue);
//            if (i_ret == FR_FAIL)
//                return FR_FAIL;
//        }
//        else
//        {
//            snprintf(arr_title, sizeof(arr_title), "NOTIFY");
//        }
//
//        if (p_st_session->p_title)
//            frfree(p_st_session->p_title);
//        p_st_session->p_title = frstrdup(arr_title);
//        if (p_st_session->p_title == NULL)
//            return FR_FAIL;
//
//        p_st_private->i_type = T3_NOTIFY;
//        strcpy(arr_key, APM_REPORT_KEY_NOTIFY);
//    }
//    else
//    {
//        // method上报
//        i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_METHOD_RESP, "GET");
//        if (i_ret == FR_FAIL)
//            return FR_FAIL;
//
//        // title
//        if (p_st_session->p_queue != NULL)
//            snprintf(arr_title, sizeof(arr_title), "GET %s", p_st_session->p_queue);
//        else
//            snprintf(arr_title, sizeof(arr_title), "GET");
//
//        if (p_st_session->p_title)
//            frfree(p_st_session->p_title);
//        p_st_session->p_title = frstrdup(arr_title);
//        if (p_st_session->p_title == NULL)
//            return FR_FAIL;
//
//        strcpy(arr_key, APM_REPORT_KEY_RESP);
//    }

    i_ret = wls_message_analysis(p_st_data, p_st_body_data, arr_key, 0, 0);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    return i_ret;
}

/*!
 * t3 浏览消息请求解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 * \param *p_st_body_data      (Frreport_body_data 上报链表)
 * \param *i_need_report       (int 是否需要上报)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __t3_browsemsg_req(L7session_t3_private *p_st_private
                               , Frbyte_Packet *p_st_data
                               , Frreport_body_data *p_st_body_data
                               , int *i_need_report)
{
    L7Session_t3 *p_st_session = NULL;
    char arr_title[64];
    uint32_t u32_flag = 0;
    int i_ret = 0;

    if (p_st_private == NULL || p_st_private->p_st_session == NULL || p_st_data == NULL)
        return FR_FAIL;

    p_st_session = p_st_private->p_st_session;

    if (bytebuff_remaining(p_st_data) < 4)
        return APM_L7_ANALYZE_TODO;

    i_ret = bytebuff_get_int(p_st_data, 4, &u32_flag, BYTE_BIG_ENDIAN);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (((u32_flag & 0xFF00) >> 8) == 0)
    {
        p_st_private->i_browse_status = 1;
        *i_need_report = T3_YES;
    }

    // method上报
    i_ret = frreport_body_l7_add_str(p_st_body_data, MQ_METHOD_REQ, "PEEK");
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    // title
    if (p_st_session->p_queue != NULL)
        snprintf(arr_title, sizeof(arr_title), "PEEK %s", p_st_session->p_queue);
    else
        snprintf(arr_title, sizeof(arr_title), "PEEK");

    if (p_st_session->p_title)
        frfree(p_st_session->p_title);
    p_st_session->p_title = frstrdup(arr_title);
    if (p_st_session->p_title == NULL)
        return FR_FAIL;

    return FR_SUCC;
}

/*!
 * t3 浏览消息解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 * \param *p_st_body_data      (Frreport_body_data   上报链表)
 * \param *i_need_report       (int 是否需要上报)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
FR_STATIC int __t3_browsemsg_resp(L7session_t3_private *p_st_private
                                , Frbyte_Packet *p_st_data
                                , Frreport_body_data *p_st_body_data
                                , int *i_need_report)
{
    char arr_size[64];
    uint8_t u8_msg_type = 0;
    int i_ret = 0;

    if (p_st_private == NULL || p_st_private->p_st_session == NULL
        || p_st_data == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 2);
    // 消息类型
    if (bytebuff_get_char(p_st_data, &u8_msg_type) == FR_FAIL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 2);
    switch (u8_msg_type)
    {
        case WLS_MAPMESSAGE:
            i_ret = wls_analysis_mapmessage(p_st_data, p_st_body_data, (char *)APM_REPORT_KEY_RESP, 1, 0, 0);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case WLS_OBJMESSAGE:
        case WLS_STREAMMESSAGE:
        case WLS_BYTEMESSAGE:
            i_ret = wls_analysis_objmessage(p_st_data, p_st_body_data, (char *)APM_REPORT_KEY_RESP, 1, 0, 0);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case WLS_MESSAGE:
        case WLS_TEXTMESSAGE:
            i_ret = wls_analysis_textmessage(p_st_data, p_st_body_data, (char *)APM_REPORT_KEY_RESP, 1, 0, 0);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        default:
            *i_need_report = T3_NO;
            return FR_SUCC;
    }

    if (i_ret == APM_L7_ANALYZE_TODO)
        return APM_L7_ANALYZE_TODO;

    snprintf(arr_size, sizeof(arr_size), "response.%s", MQ_REPORT_MESSAGE_SIZE);
    // 消息个数上报
    i_ret = frreport_body_l7_add_int(p_st_body_data, arr_size, 1);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    p_st_private->i_browse_status = 2;
    *i_need_report = T3_YES;

    return FR_SUCC;
}

/*!
 * t3请求解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *i_need_report       (int      是否需要上报)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
int t3_analysis_req(L7session_t3_private *p_st_private
                  , Frbyte_Packet *p_st_data
                  , Frreport_body_data *p_st_body_data
                  , int *i_need_report)
{
    Protocol_info_t3 *p_st_protocol_info = NULL;
    L7Session_t3 *p_st_session = NULL;
    uint8_t u8_type = 0;
    uint8_t u8_flag = 0;
    char arr_server[64];
    int i_ret = 0;

    if (p_st_data == NULL || p_st_body_data == NULL  || p_st_private == NULL
        || p_st_private->p_st_protocol_info == NULL
        || p_st_private->p_st_session == NULL
        || p_st_private->p_st_fragment == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 7)
        return APM_L7_ANALYZE_TODO;

    *i_need_report = T3_NO;

    p_st_protocol_info = p_st_private->p_st_protocol_info;
    p_st_session = p_st_private->p_st_session;

    bytebuff_skip(p_st_data, 4);
    i_ret = bytebuff_get_char(p_st_data, &u8_type);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    if (u8_type == 4)
        p_st_private->i_responserequired = 0;
    else
        p_st_private->i_responserequired = 1;

    bytebuff_skip(p_st_data, 1);
    i_ret = bytebuff_get_char(p_st_data, &u8_flag);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    // session server
    if (p_st_session->p_server == NULL)
    {
        if (p_st_protocol_info->p_version != NULL)
        {
            snprintf(arr_server, sizeof(arr_server), "weblogic-%s", p_st_protocol_info->p_version);
            p_st_session->p_server = frstrdup(arr_server);
            if (p_st_session->p_server == NULL)
                return FR_FAIL;
        }
        else // 长连接没有版本信息
        {
            p_st_session->p_server = frstrdup("weblogic");
            if (p_st_session->p_server == NULL)
                return FR_FAIL;
        }
    }

    if (__t3_get_responseid(p_st_private, p_st_data) == FR_FAIL)
        return FR_FAIL;

    // EJB
    if (p_st_private->is_ejb == 1)
    {
        i_ret = t3_ejb_analysis_req(p_st_private, p_st_data, p_st_body_data, i_need_report);
        return i_ret;
    }

    if (u8_flag != 0)
    {
        if (p_st_private->p_st_fragment->u32_left_len != 0)
        {
            bytebuff_set_skip(p_st_data, p_st_private->p_st_fragment->u32_left_len);
            return APM_L7_ANALYZE_TODO;
        }
        p_st_private->ui_responseid = 0;
        return FR_SUCC;
    }

    if (__t3_get_methodid(p_st_private, p_st_data) == FR_FAIL)
        return FR_FAIL;

    switch (p_st_private->i_methodid)
    {
        case 4872:  // ProducerCreate(\x13\x08)
            i_ret = __t3_producer_create(p_st_private, p_st_data);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case 520: // BrowseCreate(\x02\x08)
            i_ret = __t3_browser_create(p_st_private, p_st_data);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case 2824:  // ConsumerCreate(\x0b\x08)
            i_ret = __t3_consumer_create(p_st_private, p_st_data, p_st_body_data, i_need_report);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        case 5129:   // send(\x14\x09)
            i_ret = __t3_sendmsg_analysis(p_st_private, p_st_data, p_st_body_data);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            *i_need_report = T3_YES;
            break;
        case 4108: // browse(\x10\x0c)
            i_ret = __t3_browsemsg_req(p_st_private, p_st_data, p_st_body_data, i_need_report);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            break;
        default:
            break;
    }

    if (i_ret == FR_SUCC && p_st_private->p_st_fragment->u32_left_len != 0)
    {
        bytebuff_set_skip(p_st_data, p_st_private->p_st_fragment->u32_left_len);
        return APM_L7_ANALYZE_TODO;
    }

    if (*i_need_report == T3_NO)
        p_st_private->ui_responseid = 0;

    return i_ret;
}

/*!
 * t3响应解析
 *
 * \param *p_st_private        (L7session_t3_private  t3私有数据)
 * \param *p_st_data           (Frbyte_Packet          数据)
 * \param *p_st_body_data      (Frreport_body_data    上报数据)
 * \param *i_need_report       (int      是否需要上报)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败\n
 *         APM_L7_ANALYZE_TODO:数据包不完整
 *
 */
int t3_analysis_resp(L7session_t3_private *p_st_private
                   , Frbyte_Packet *p_st_data
                   , Frreport_body_data *p_st_body_data
                   , int *i_need_report)
{
    Protocol_info_t3 *p_st_protocol_info = NULL;
    L7Session_t3 *p_st_session = NULL;
    uint8_t u8_type = 0;
    uint32_t u32_respid = 0;
    uint32_t u32_methodid = 0;
    uint32_t u32_flag = 0;
    char arr_server[64];
    int i_idx = 0;
    int i_ret = 0;

    if (p_st_data == NULL || p_st_body_data == NULL  || p_st_private == NULL
        || p_st_private->p_st_protocol_info == NULL
        || p_st_private->p_st_session == NULL
        || p_st_private->p_st_fragment == NULL)
        return FR_FAIL;

    if (bytebuff_remaining(p_st_data) < 14)
        return FR_SUCC;

    p_st_protocol_info = p_st_private->p_st_protocol_info;
    p_st_session = p_st_private->p_st_session;

    bytebuff_skip(p_st_data, 4);
    i_ret = bytebuff_get_char(p_st_data, &u8_type);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    bytebuff_skip(p_st_data, 2);

    if (bytebuff_get_int(p_st_data, 4, &u32_respid, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;

    *i_need_report = T3_NO;

    // session server
    if (p_st_protocol_info->p_version != NULL && p_st_session->p_server == NULL)
    {
        snprintf(arr_server, sizeof(arr_server), "weblogic-%s", p_st_protocol_info->p_version);
        p_st_session->p_server = frstrdup(arr_server);
        if (p_st_session->p_server == NULL)
            return FR_FAIL;
    }

    if (bytebuff_remaining(p_st_data) < 12)
        return FR_SUCC;

    // 头部结束
    bytebuff_skip(p_st_data, 8);

    i_ret = frreport_body_l7_add_int(p_st_body_data, "response.code", 0);
    if (i_ret == FR_FAIL)
        return FR_FAIL;

    // 区分是JMS或EJB
    if (bytebuff_memstr(p_st_data, bytebuff_getPosition(p_st_data), 0, WEBLOGIC_EJB_BUSINESSOBJ, strlen(WEBLOGIC_EJB_BUSINESSOBJ), &i_idx) != FR_FAIL
         || p_st_private->is_ejb == 1)
    {
        p_st_private->is_ejb = 1;

        i_ret = t3_ejb_analysis_resp(p_st_private, p_st_data, p_st_body_data, i_need_report);
        return i_ret;
    }

    if (bytebuff_get_int(p_st_data, 4, &u32_flag, BYTE_BIG_ENDIAN) == FR_FAIL)
        return FR_FAIL;
    if ((u32_flag & 0x1000) && p_st_private->i_browse_status == 1)
    {
        i_ret = __t3_browsemsg_resp(p_st_private, p_st_data, p_st_body_data, i_need_report);
        if (i_ret == FR_FAIL)
            return FR_FAIL;
        if (u32_respid != 0 && u32_respid == p_st_private->ui_responseid)
            return FR_SUCC;
        else
        {
            *i_need_report = T3_NO;
            return FR_SUCC;
        }
    }
    else
    {
        if (bytebuff_remaining(p_st_data) < 14)
            return FR_SUCC;
        bytebuff_skip(p_st_data, 10);
        if (bytebuff_get_int(p_st_data, 4, &u32_methodid, BYTE_BIG_ENDIAN) == FR_FAIL)
            return FR_FAIL;
    }

    if (u32_respid != 0 && u32_respid == p_st_private->ui_responseid)
    {
        *i_need_report = T3_YES;
        return FR_SUCC;
    }

    switch (u32_methodid)
    {
        case 15620:  // PushMessage(\x3d\x04)
            i_ret = __t3_pushmsg_analysis(p_st_private, p_st_data, p_st_body_data);
            if (i_ret == FR_FAIL)
                return FR_FAIL;
            *i_need_report = T3_YES;
            break;
        default:
            break;
    }

    if (i_ret == FR_SUCC && p_st_private->p_st_fragment->u32_left_len != 0)
    {
        bytebuff_set_skip(p_st_data, p_st_private->p_st_fragment->u32_left_len);
        return APM_L7_ANALYZE_TODO;
    }

    return i_ret;
}
